package top.tangyh.lamp.care.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import jakarta.annotation.Resource;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import top.tangyh.basic.base.service.impl.SuperServiceImpl;
import top.tangyh.lamp.care.entity.BPgRecord;
import top.tangyh.lamp.care.manager.BPgRecordManager;
import top.tangyh.lamp.care.mapper.DsValMapper;
import top.tangyh.lamp.care.service.DsPickSevice;
import top.tangyh.lamp.care.service.DsValSevice;
import top.tangyh.lamp.care.vo.query.DsInVo;
import top.tangyh.lamp.care.vo.result.DsCellVO;
import top.tangyh.lamp.care.vo.result.DsOutVO;
import top.tangyh.lamp.care.vo.save.DsPickInVO;

import java.util.*;

@Slf4j
@Service
public class DsValSeviceImpl    implements DsValSevice {
	@Resource
	private  DsValMapper dsValMapper;

	/**
	 * 采集时间前几分钟
	 */
	private final int PRE_MINUTE = -5;
	/**
	 * 一级数据源 评估评分
	 */
	private final static String SRC1_PGPF = "1";
	/**
	 * 一级数据源 观察项
	 */
	private final static String SRC1_GCX = "2";
	/**
	 * 一级数据源 化验单
	 */
	private final static String SRC1_HYD = "3";
	/**
	 * 一级数据源 入量
	 */
	private final static String SRC1_IN = "4";
	/**
	 * 一级数据源 出量
	 */
	private final static String SRC1_OUT = "5";
	/**
	 * 二级数据源 评评评分 医生
	 */
	private final static String SRC2_PGPF_DOCTOR = "1";
	/**
	 * 二级数据源 评评评分 护士
	 */
	private final static String SRC2_PGPF_NURSE = "2";
	/**
	 * 二级数据源 评评评分 合部
	 */
	private final static String SRC2_PGPF_ALL = "3";

	/**
	 * 在通用项目中，入量类型CODE
	 */
	private final static String YX_IN = "crl-in";

	/**
	 * 在通用项目中，出量类型CODE
	 */
	private final static String YX_OUT = "crl-out";

	/**
	 * 只含有时的时间格式
	 */
	private final static String DATE_TO_HOUR = "yyyy-MM-dd HH";

	/**
	 * 各数据源具体取值实现存储,key为一级数据值，value为具体查询数据实现对象
	 */
	private Map<String, DsPickSevice> dsPickSeviceMap = new HashMap<>();

	public DsValSeviceImpl() {
		//观察项
		dsPickSeviceMap.put(SRC1_GCX, dsPick -> pickObsrv(dsPick));
		//入量
		dsPickSeviceMap.put(SRC1_IN, dsPick -> pickIn(dsPick));
		//出量
		dsPickSeviceMap.put(SRC1_OUT, dsPick -> pickOut(dsPick));
		//评估评分
		dsPickSeviceMap.put(SRC1_PGPF, dsPick -> pickPgpf(dsPick));
	}


	/**
	 * 数据源取值查询
	 *
	 * @param param 查询值参数
	 */
	@Override
	public List<DsOutVO> getDsVals(DsInVo param) {
		List<DsOutVO> rst = dsValMapper.getDsVals(param);
		for (DsOutVO dsOutVO : rst) {
			DsPickInVO dsPickInVO = new DsPickInVO(param.getHospitalNumber(), param.getMappedTime(), dsOutVO.getSrcL1(), dsOutVO.getSrcL2(), dsOutVO.getSrcL3());
			DsPickSevice sevice = dsPickSeviceMap.get(dsPickInVO.getSrcL1());
			dsOutVO.setResult(sevice.pick(dsPickInVO));
		}
		return rst;
	}


	/**
	 * 获取观察项值
	 *
	 * @param param 查询值参数
	 * @return
	 */
	public List<DsCellVO> pickObsrv(DsPickInVO param) {
		param.setMappedTimeStart(DateUtil.offsetMinute(new Date(param.getMappedTime()), PRE_MINUTE).getTime());
		List<DsCellVO> rst = new ArrayList<>();
		if (!SRC1_GCX.equals(param.getSrcL1())) {
			return rst;
		}
		rst = dsValMapper.pickObsrv(param);
		return rst;
	}

	/**
	 * 获取输入量
	 *
	 * @param param 查询值参数
	 * @return
	 */
	public List<DsCellVO> pickIn(DsPickInVO param) {
		//todo 出入量约定：一级数据源为 类型 SRC1_IN 或SRC1_OUT, 二级数据源约定为记录明间到采集时间之间累加求和间隔,单位小时，三级数据源为 出入量类型
		List<DsCellVO> rst = new ArrayList<>();
		if (!SRC1_IN.equals(param.getSrcL1())) {
			return rst;
		}
		//时间处理
		DsPickInVO newParam = doIoParamByTimeBy77(param);
		//改变srcL2含义,存放模块名
		newParam.setSrcL2(YX_IN);
		rst = dsValMapper.pickIo(newParam);
		return rst;
	}

	/**
	 * 获取输出量
	 *
	 * @param param 查询值参数
	 * @return
	 */
	public List<DsCellVO> pickOut(DsPickInVO param) {
		//todo 出入量约定：一级数据源为 类型 SRC1_IN 或SRC1_OUT, 二级数据源约定为记录明间到采集时间之间累加求和间隔,单位小时，三级数据源为 出入量类型
		List<DsCellVO> rst = new ArrayList<>();
		if (!SRC1_OUT.equals(param.getSrcL1())) {
			return rst;
		}
		//时间处理
		DsPickInVO newParam = doIoParamByTimeBy77(param);
		//改变srcL2含义,存放模块名
		newParam.setSrcL2(YX_OUT);
		rst = dsValMapper.pickIo(newParam);
		return rst;
	}

	/**
	 * 处理输入量、输出量的查询参数的时间处理，固定>=昨天7点整 ，<今天7点
	 *
	 * @param param 查询值参数
	 * @return
	 */
	private DsPickInVO doIoParamByTimeBy77(DsPickInVO param) {
		DsPickInVO newParam = BeanUtil.copyProperties(param, DsPickInVO.class);
		Date appliyDate = new Date(param.getMappedTime());
		//获得指定时间年月日
		appliyDate = DateUtil.beginOfDay(appliyDate);
		//获得昨天7点时间
		Date mappedDateStart = DateUtil.offsetHour(appliyDate, -17);
		Date mappedDate = DateUtil.offsetHour(appliyDate, 7);
		//注意这里是精确到秒是10位时间戳
		newParam.setMappedTimeStart(mappedDateStart.getTime());
		newParam.setMappedTime(mappedDate.getTime());
		return newParam;
	}

	/**
	 * 处理输入量、输出量的查询参数的时间
	 *
	 * @param param 查询值参数
	 * @return
	 */
	private DsPickInVO doIoParamByTime(DsPickInVO param) {
		DsPickInVO newParam = BeanUtil.copyProperties(param, DsPickInVO.class);
		Date appliyDate = new Date(param.getMappedTime());
		//获得当前时间的 年月日时，（分钟及以后不要）
		appliyDate = DateUtil.parse(DateUtil.format(appliyDate, DATE_TO_HOUR), DATE_TO_HOUR);
		//当前年月日时时间减去数据源2间隔时间
		Date mappedDateStart = DateUtil.offsetHour(appliyDate, -Convert.toInt(param.getSrcL2()));
		//注意这里是精确到秒是10位时间戳
		newParam.setMappedTimeStart(mappedDateStart.getTime());
		newParam.setMappedTime(appliyDate.getTime());
		return newParam;
	}

	/**
	 * 获取评估评分结果
	 *
	 * @param param 查询值参数
	 * @return
	 */
	public List<DsCellVO> pickPgpf(DsPickInVO param) {
		List<DsCellVO> rst = new ArrayList<>();
		if (!SRC1_PGPF.equals(param.getSrcL1())) {
			return rst;
		}
		rst = dsValMapper.pickPgpf(param);
		return rst;
	}

}